package com.distribute.core.core;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.distribute.common.ReportEntity;
import com.distribute.core.constants.LocalCacheConstants;
import com.distribute.core.utils.SpringContextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * 缓存管理
 *
 * @author chennengcheng
 * @date 2021-01-15 11:42
 * @remark
 */
public class CacheManageContext {

    private static final Logger log = LoggerFactory.getLogger(CacheManageContext.class);

    private static final Map<String, Map<String, String>> CACHE_CELL_MAP = new HashMap<>();

    /**
     *
     * @param modelPrefixName
     * @param modelName
     * @param className
     */
    public static void addCell(String modelPrefixName, String modelName, String className) {
        Map<String, String> modelPrefixNameMap = CACHE_CELL_MAP.get(modelPrefixName);
        if (CollectionUtil.isEmpty(modelPrefixNameMap)) {
            modelPrefixNameMap = new HashMap<>();
            modelPrefixNameMap.put(modelName, className);
            CACHE_CELL_MAP.put(modelPrefixName, modelPrefixNameMap);
            return;
        }

        String classNameOld = modelPrefixNameMap.get(modelName);
        if (StrUtil.isNotEmpty(classNameOld)) {
            log.error("同一业务缓存模块不允许存在相同模块名，请检查 " + classNameOld);
            return;
        }


        modelPrefixNameMap.put(modelName, className);
        CACHE_CELL_MAP.put(modelPrefixName, modelPrefixNameMap);
    }

    /**
     *
     * @param modelPrefixName
     */
    public static String getClassNameByModeFullName(String modelPrefixName, String modelName) {
        Map<String, String> modelPrefixNameMap = CACHE_CELL_MAP.get(modelPrefixName);
        if (CollectionUtil.isEmpty(modelPrefixNameMap)) {
            log.error("不存在业务缓存模块，请检查 " + modelPrefixName);
            return StrUtil.EMPTY;
        }

        return modelPrefixNameMap.get(modelName);
    }


    /**
     * 获得模板解析器
     * @param modelPrefix
     * @param modelName
     * @return
     */
    public static BaseCacheManageCell<BaseNotifyMessage> getBeanParser(String modelPrefix, String modelName) {
        if (StrUtil.isBlank(modelPrefix)) {
            log.info("未找到对应缓存管理器，请检查 " + modelPrefix);
            return new DefaultGuavaLoadingCacheCellImpl();
        }

        String beanName = getClassNameByModeFullName(modelPrefix, modelName);
        if (StrUtil.isBlank(beanName)) {
            log.info("未找到对应缓存管理器，请检查 " + modelPrefix + "-" + modelName);
            return new DefaultGuavaLoadingCacheCellImpl();
        }

        return (BaseCacheManageCell) SpringContextUtils.getBean(beanName);
    }

    /**
     * 初始化
     */
    public static void globalInit() throws ExecutionException, InterruptedException {
        // 正在初始化 模块、具体、本地缓存
        if (CollectionUtil.isEmpty(CACHE_CELL_MAP)) {
            return;
        }

        long startTime = System.currentTimeMillis();
        List<CompletableFuture<Void>> completableFutures = new ArrayList<>();
        for (Map<String, String> cellMaps : CACHE_CELL_MAP.values()) {
            if (CollectionUtil.isEmpty(cellMaps.values())) {
                continue;
            }
            for (String name : cellMaps.values()){
                BaseCacheManageCell cacheCell = (BaseCacheManageCell) SpringContextUtils.getBean(name);
                CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(cacheCell::init);
                completableFutures.add(completableFuture);
            }
        }

        //等待子线程任务完成
        try {
            CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).get();
        } catch (InterruptedException | ExecutionException e) {
            log.error("本地缓存初始化失败： ", e);
            throw e;
        }

        log.info("结束初始化本地缓存，共耗时：{}ms", (System.currentTimeMillis() - startTime));
    }

    /**
     * 获取初始化上报实体信息
     * @return
     */
    public static List<ReportEntity> getReportEntityList(){
        List<ReportEntity> reportEntities = new ArrayList<>();
        for (Map<String, String> cellMaps : CACHE_CELL_MAP.values()){
            Collection<String> beanNames = cellMaps.values();
            if (CollectionUtil.isEmpty(beanNames)) {
                continue;
            }

            List<ReportEntity> reportEntityList =
                    beanNames.stream()
                            .map(CacheManageContext::getCacheReportEntity)
                            .collect(Collectors.toList());
            reportEntities.addAll(reportEntityList);
        }

        return reportEntities;
    }

    /**
     * 初始化上报实体信息
     * @param cacheClassName
     * @return
     */
    public static ReportEntity getCacheReportEntity(String cacheClassName){
        BaseCacheManageCell cacheCell = (BaseCacheManageCell) SpringContextUtils.getBean(cacheClassName);
        return ReportEntity.getInstance(
                LocalCacheConstants.getIp(),
                LocalCacheConstants.getActiveProfile(),
                LocalCacheConstants.getServiceName(),
                LocalCacheConstants.getNotifyPluginType(),
                cacheCell.getModelPrefix(),
                cacheCell.getModel(),
                cacheCell.getCacheClassSimpleName(),
                cacheCell.size(),
                cacheCell.status.get());
    }

}
